Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,61 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### ⚠️ Breaking Changes

- Support periodic flip parity for external cells [#391](https://github.com/acgetchell/delaunay/pull/391)
- Replace public core module with focused facades

### Merged Pull Requests

- Support periodic flip parity for external cells [#391](https://github.com/acgetchell/delaunay/pull/391)
- Refactor/387 tds mutation boundaries [#390](https://github.com/acgetchell/delaunay/pull/390)
- Refresh release docs and benchmark guidance [#389](https://github.com/acgetchell/delaunay/pull/389)

Comment thread
coderabbitai[bot] marked this conversation as resolved.
### Added

- [**breaking**] Support periodic flip parity for external cells [#391](https://github.com/acgetchell/delaunay/pull/391)
[`5fb2d4a`](https://github.com/acgetchell/delaunay/commit/5fb2d4a22927231ba3396950cf2bbbc481f69285)

- Preserve periodic vertex offsets when bistellar flips build replacement cells.
- Align external-facet parity checks across periodic cell frames instead of rejecting periodic external cells.
- Surface replacement periodic-offset shape and frame conflicts with typed flip-context errors.

### Changed

- Refactor/387 tds mutation boundaries [#390](https://github.com/acgetchell/delaunay/pull/390)
[`da30293`](https://github.com/acgetchell/delaunay/commit/da3029302e8484d26d2a88d1291050c332e6b822)

- [**breaking**] Replace public core module with focused facades
[`3fc95ea`](https://github.com/acgetchell/delaunay/commit/3fc95ea62325111c927127a48d4fbd39873dabda)

- Make `crate::core` private and expose low-level APIs through curated
`tds`, `collections`, `algorithms`, and `query` modules.

- Add focused prelude/docs coverage for the new public import paths.
- Update downstream-style tests and doctests to stop relying on
`delaunay::core`.

### Documentation

- Refresh release docs and benchmark guidance [#389](https://github.com/acgetchell/delaunay/pull/389)
[`526583c`](https://github.com/acgetchell/delaunay/commit/526583c627d32d9336910bce1913b7f458ca413c)

- Update the README pitch, feature list, references, and docs.rs-facing guidance
around exact predicates, SoS, PL-manifold validation, and bistellar repair.

- Refresh roadmap, release, limitation, robustness, orientation, invariant,
diagnostics, property-testing, workflow, and validation docs for the v0.7.8
cleanup path and v0.8.0 paper-facing work.

- Align contributor and script docs around non-mutating `just` checks before
mutating fixes.

- Update generated benchmark-summary guidance to surface `just bench-perf-summary`,
current Criterion metadata, and large-scale characterization defaults.

## [0.7.7] - 2026-05-15

### ⚠️ Breaking Changes
Expand Down Expand Up @@ -3376,6 +3431,7 @@ Older releases are archived by minor series:
- [0.3.x](docs/archive/changelog/0.3.md)
- [0.2.x](docs/archive/changelog/0.2.md)

[Unreleased]: https://github.com/acgetchell/delaunay/compare/v0.7.7...HEAD
[0.7.7]: https://github.com/acgetchell/delaunay/compare/v0.7.6...v0.7.7
[0.7.6]: https://github.com/acgetchell/delaunay/compare/v0.7.5...v0.7.6
[0.7.5]: https://github.com/acgetchell/delaunay/compare/v0.7.4...v0.7.5
Expand Down
27 changes: 27 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,33 @@ Follow the patterns documented in [code organization documentation][code-organiz
7. Trait implementations
8. Tests (comprehensive with subsections)

### Public Namespace Policy

`src/core/` is the internal implementation namespace for the low-level TDS and
algorithm layer. Do not make `crate::core` public or add a broad
`delaunay::core` facade. The public low-level surface should stay explicit and
workflow-oriented:

- `delaunay::tds` for cells, facets, vertex keys, TDS validation, and generic
triangulation data structures
- `delaunay::collections` for collection aliases, small buffers, and secondary
maps
- `delaunay::algorithms` for low-level algorithms such as point location and
Hilbert ordering
- `delaunay::query` for read-only traversal, convex hull extraction, boundary
analysis, and diagnostics helpers

Expose new low-level APIs through those curated modules and their focused
preludes when the item is useful to downstream callers. Keep high-level
Delaunay construction, repair, validation policy, and workflow APIs separate
from this layer so imports describe the level of abstraction being used.

During pre-1.0 development, breaking import changes are acceptable when they
improve correctness, orthogonality, or performance. When changing the public
surface, update the facade modules in `src/lib.rs`, the focused preludes,
README import guidance, code-organization docs, doctests, and any
downstream-style integration tests that demonstrate supported imports.

## Testing

### Test Categories
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,14 @@ intent. The broad `delaunay::prelude::triangulation::*` import is retained for
compatibility, but new docs and tests should prefer the narrow workflow preludes
above.

### Low-level imports

`delaunay::core` is an internal implementation namespace. Public low-level APIs
are exposed through `delaunay::tds`, `delaunay::collections`,
`delaunay::algorithms`, and `delaunay::query`, plus the matching focused
preludes. Contributors should follow the namespace policy in
[CONTRIBUTING.md](CONTRIBUTING.md) and [docs/code_organization.md](docs/code_organization.md).

```rust
use delaunay::prelude::triangulation::construction::{
DelaunayTriangulationBuilder, DelaunayTriangulationConstructionError, vertex,
Expand Down
7 changes: 7 additions & 0 deletions docs/code_organization.md
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,13 @@ The `benchmark-utils` CLI provides integrated benchmark workflow functionality,
- `canonical_points.rs` - Canonical vertex-ordering helpers for geometric predicate call sites (SoS consistency)
- `operations.rs` - Semantic classification and telemetry for topological operations

Public namespace policy: `crate::core` is the internal implementation namespace
for the low-level TDS and algorithm layer. The public low-level surface is
exposed through curated modules and focused preludes (`delaunay::tds`,
`delaunay::collections`, `delaunay::algorithms`, `delaunay::query`, and their
`delaunay::prelude::*` counterparts) rather than a broad public
`delaunay::core` module.

**`src/geometry/`** - Geometric algorithms and predicates:

- `kernel.rs` - Kernel abstraction (`AdaptiveKernel` default, `RobustKernel`, `FastKernel`) and `ExactPredicates` marker trait
Expand Down
4 changes: 2 additions & 2 deletions docs/dev/debug_env_vars.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ This matters for large-scale investigations that need to run under
| Variable | Activation | Module | Description |
|---|---|---|---|
| `DELAUNAY_INSERT_TRACE` | presence | `triangulation.rs` | `[release]` Per-insertion summary (vertex index, location, conflict size, suspicion flags) |
| `DELAUNAY_BULK_PROGRESS_EVERY` | **value** (integer) | `triangulation/delaunay.rs` | `[release]` Periodic batch progress plus retry-boundary output. |
| `DELAUNAY_BULK_PROGRESS_EVERY` | **value** (integer) | `triangulation/delaunay.rs` | `[release]` Periodic batch progress for post-simplex bulk vertices. |
| `DELAUNAY_DEBUG_CAVITY_REDUCTION_ONCE` | presence | `triangulation.rs` | `[release]` One-shot trace of first cavity reduction chain + re-extractions. |
| `DELAUNAY_DEBUG_RETRYABLE_SKIP` | presence | `triangulation.rs` | `[release]` Retryable conflict skip trace with attempt and rollback context. |
| `DELAUNAY_DEBUG_SHUFFLE` | presence | `triangulation.rs` | Logs vertex shuffle order during batch construction |
Expand Down Expand Up @@ -132,7 +132,7 @@ and release builds.
| `DELAUNAY_LARGE_DEBUG_INITIAL_SIMPLEX` | **value** | Batch initial simplex strategy: `max-volume` (default), `balanced`, or `first` |
| `DELAUNAY_LARGE_DEBUG_DEBUG_MODE` | **value** | `cadenced` (ridge-link) or `strict` (per-insertion vertex-link) |
| `DELAUNAY_LARGE_DEBUG_SHUFFLE_SEED` | **value** | Vertex shuffle seed |
| `DELAUNAY_LARGE_DEBUG_PROGRESS_EVERY` | **value** | Progress logging interval |
| `DELAUNAY_LARGE_DEBUG_PROGRESS_EVERY` | **value** | Incremental progress interval; batch fallback if the canonical knob is unset |
| `DELAUNAY_LARGE_DEBUG_VALIDATE_EVERY` | **value** | Validation interval |
| `DELAUNAY_LARGE_DEBUG_REPAIR_EVERY` | **value** | Batch/incremental repair interval (default: 1) |
| `DELAUNAY_LARGE_DEBUG_REPAIR_MAX_FLIPS` | **value** | Flip budget override |
Expand Down
2 changes: 1 addition & 1 deletion docs/numerical_robustness_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ See `validate_cell_coordinate_uniqueness` in
### User-facing dedup utilities

For explicit preprocessing, the crate provides public deduplication functions in
`core::util`:
`delaunay::prelude::triangulation`:

- `dedup_vertices_exact(&[Vertex])` — removes exact coordinate duplicates (O(n²))
- `dedup_vertices_epsilon(&[Vertex], epsilon)` — removes near-duplicates within
Expand Down
7 changes: 4 additions & 3 deletions docs/production_review_remediation_checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,10 @@ Treat partial items as still open until their acceptance notes are satisfied.
- [ ] **25. Protect `Vertex::incident_cell` mutation.**
Introduce a checked setter or newtype so invalid incident-cell links are
harder to construct. Tracked for v0.7.8 in #387.
- [ ] **26. Revisit public `core` module naming.**
Decide whether to keep the shadowing surface, rename it, or hide it behind
curated exports. Tracked for v0.7.8 in #388.
- [x] **26. Revisit public `core` module naming.**
Keep `crate::core` as the internal implementation namespace, and expose the
public low-level surface through curated modules and focused preludes such as
`tds`, `collections`, `algorithms`, and `query`. Tracked for v0.7.8 in #388.
- [ ] **27. Normalize boxing policy in Delaunay repair error variants.**
Pick a consistent enum-size and payload strategy. Tracked for v0.7.8 in #384.

Expand Down
12 changes: 6 additions & 6 deletions docs/validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -571,12 +571,12 @@ converge, consider the opt-in heuristic rebuild fallback via

| Level | Method | Module | Complexity |
|-------|--------|--------|------------|
| 1 | `Cell::is_valid()` | `core::cell` | O(1) |
| 1 | `Vertex::is_valid()` | `core::vertex` | O(1) |
| 2 | `Tds::is_valid()` | `core::tds` | O(N×D²) |
| 2 | `Tds::validate()` | `core::tds` | O(N×D²) |
| 3 | `Triangulation::is_valid()` | `core::triangulation` | O(N×D²) |
| 3 | `Triangulation::validate()` | `core::triangulation` | O(N×D²) |
| 1 | `Cell::is_valid()` | `tds` | O(1) |
| 1 | `Vertex::is_valid()` | `tds` | O(1) |
| 2 | `Tds::is_valid()` | `tds` | O(N×D²) |
| 2 | `Tds::validate()` | `tds` | O(N×D²) |
| 3 | `Triangulation::is_valid()` | `triangulation` | O(N×D²) |
| 3 | `Triangulation::validate()` | `triangulation` | O(N×D²) |
| 4 | `DelaunayTriangulation::is_valid()` | `triangulation::delaunay` | O(cells) |
| 4 | `DelaunayTriangulation::validate()` | `triangulation::delaunay` | O(cells × D²) + O(cells) |
| — | `DelaunayTriangulation::validation_report()` | `triangulation::delaunay` | O(cells × D²) + O(cells) |
Expand Down
45 changes: 23 additions & 22 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ cargo_llvm_cov_version := "0.8.5"
# Common cargo-llvm-cov arguments for all coverage runs.
# Excludes benches/examples from reports while allowing integration tests to
# exercise library code.
[private]
_coverage_base_args := '''--ignore-filename-regex '(^|/)(benches|examples)/' \
--workspace --lib --tests \
--verbose'''
Expand All @@ -25,7 +26,7 @@ _ensure-cargo-llvm-cov:
set -euo pipefail
if ! command -v cargo-llvm-cov >/dev/null; then
echo "❌ 'cargo-llvm-cov' not found. See 'just setup-tools' or install:"
echo " cargo install --locked cargo-llvm-cov --version {{cargo_llvm_cov_version}}"
echo " cargo install --locked cargo-llvm-cov --version {{ cargo_llvm_cov_version }}"
exit 1
fi

Expand Down Expand Up @@ -162,12 +163,12 @@ changelog: _ensure-git-cliff python-sync
uv run archive-changelog

changelog-tag version:
just tag {{version}}
just tag {{ version }}

changelog-unreleased version: _ensure-git-cliff python-sync
#!/usr/bin/env bash
set -euo pipefail
GIT_CLIFF_OFFLINE=true git-cliff --tag {{version}} -o CHANGELOG.md
GIT_CLIFF_OFFLINE=true git-cliff --tag {{ version }} -o CHANGELOG.md
uv run postprocess-changelog
uv run archive-changelog

Expand All @@ -192,7 +193,7 @@ ci: check test examples
# CI followed by an explicit persistent local baseline refresh.
ci-baseline ref="main":
just ci
just perf-baseline {{ref}}
just perf-baseline {{ ref }}

# CI + slow/stress tests (100+ vertices, stress tests)
ci-slow: ci test-slow
Expand All @@ -219,25 +220,25 @@ clippy:
# Coverage analysis for local development (HTML output)
coverage: _ensure-cargo-llvm-cov
mkdir -p target/llvm-cov
cargo llvm-cov {{_coverage_base_args}} --html --output-dir target/llvm-cov
cargo llvm-cov {{ _coverage_base_args }} --html --output-dir target/llvm-cov
@echo "📊 Coverage report generated: target/llvm-cov/html/index.html"

# Coverage analysis for CI (XML output for codecov/codacy)
coverage-ci: _ensure-cargo-llvm-cov
mkdir -p coverage
cargo llvm-cov {{_coverage_base_args}} --cobertura --output-path coverage/cobertura.xml -- --skip prop_
cargo llvm-cov {{ _coverage_base_args }} --cobertura --output-path coverage/cobertura.xml -- --skip prop_

debug-large-scale-2d n="36000" repair_every="1":
DELAUNAY_BULK_PROGRESS_EVERY=2000 DELAUNAY_LARGE_DEBUG_MAX_RUNTIME_SECS=1800 DELAUNAY_LARGE_DEBUG_N_2D={{n}} DELAUNAY_LARGE_DEBUG_REPAIR_EVERY={{repair_every}} cargo test --release --test large_scale_debug debug_large_scale_2d -- --ignored --exact --nocapture
DELAUNAY_BULK_PROGRESS_EVERY=2000 DELAUNAY_LARGE_DEBUG_MAX_RUNTIME_SECS=1800 DELAUNAY_LARGE_DEBUG_N_2D={{ n }} DELAUNAY_LARGE_DEBUG_REPAIR_EVERY={{ repair_every }} cargo test --release --test large_scale_debug debug_large_scale_2d -- --ignored --exact --nocapture

debug-large-scale-3d n="8000" repair_every="1":
DELAUNAY_BULK_PROGRESS_EVERY=500 DELAUNAY_LARGE_DEBUG_MAX_RUNTIME_SECS=1800 DELAUNAY_LARGE_DEBUG_N_3D={{n}} DELAUNAY_LARGE_DEBUG_REPAIR_EVERY={{repair_every}} cargo test --release --test large_scale_debug debug_large_scale_3d -- --ignored --exact --nocapture
DELAUNAY_BULK_PROGRESS_EVERY=500 DELAUNAY_LARGE_DEBUG_MAX_RUNTIME_SECS=1800 DELAUNAY_LARGE_DEBUG_N_3D={{ n }} DELAUNAY_LARGE_DEBUG_REPAIR_EVERY={{ repair_every }} cargo test --release --test large_scale_debug debug_large_scale_3d -- --ignored --exact --nocapture

debug-large-scale-4d n="900" repair_every="1":
DELAUNAY_BULK_PROGRESS_EVERY=100 DELAUNAY_LARGE_DEBUG_MAX_RUNTIME_SECS=1800 DELAUNAY_LARGE_DEBUG_N_4D={{n}} DELAUNAY_LARGE_DEBUG_REPAIR_EVERY={{repair_every}} cargo test --release --test large_scale_debug debug_large_scale_4d -- --ignored --exact --nocapture
DELAUNAY_BULK_PROGRESS_EVERY=100 DELAUNAY_LARGE_DEBUG_MAX_RUNTIME_SECS=1800 DELAUNAY_LARGE_DEBUG_N_4D={{ n }} DELAUNAY_LARGE_DEBUG_REPAIR_EVERY={{ repair_every }} cargo test --release --test large_scale_debug debug_large_scale_4d -- --ignored --exact --nocapture

debug-large-scale-5d n="140" repair_every="1":
DELAUNAY_BULK_PROGRESS_EVERY=20 DELAUNAY_LARGE_DEBUG_MAX_RUNTIME_SECS=1800 DELAUNAY_LARGE_DEBUG_N_5D={{n}} DELAUNAY_LARGE_DEBUG_REPAIR_EVERY={{repair_every}} cargo test --release --test large_scale_debug debug_large_scale_5d -- --ignored --exact --nocapture
DELAUNAY_BULK_PROGRESS_EVERY=20 DELAUNAY_LARGE_DEBUG_MAX_RUNTIME_SECS=1800 DELAUNAY_LARGE_DEBUG_N_5D={{ n }} DELAUNAY_LARGE_DEBUG_REPAIR_EVERY={{ repair_every }} cargo test --release --test large_scale_debug debug_large_scale_5d -- --ignored --exact --nocapture

# Default recipe shows available commands
default:
Expand Down Expand Up @@ -361,15 +362,15 @@ markdown-lint: markdown-check
perf-baseline ref="main": _ensure-uv
#!/usr/bin/env bash
set -euo pipefail
uv run benchmark-utils generate-ref-baseline --ref "{{ref}}" --out baseline-artifact --dev
uv run benchmark-utils generate-ref-baseline --ref "{{ ref }}" --out baseline-artifact --dev

perf-baseline-to out ref="main": _ensure-uv
#!/usr/bin/env bash
set -euo pipefail
uv run benchmark-utils generate-ref-baseline --ref "{{ref}}" --out "{{out}}" --dev
uv run benchmark-utils generate-ref-baseline --ref "{{ ref }}" --out "{{ out }}" --dev

perf-compare file threshold="7.5": _ensure-uv
uv run benchmark-utils compare --baseline "{{file}}" --threshold {{threshold}} --dev
uv run benchmark-utils compare --baseline "{{ file }}" --threshold {{ threshold }} --dev

perf-help:
@echo "Performance Analysis Commands:"
Expand Down Expand Up @@ -422,7 +423,7 @@ perf-large-scale-smoke max_secs="60":
#!/usr/bin/env bash
set -euo pipefail

max_secs="{{max_secs}}"
max_secs="{{ max_secs }}"
if [[ ! "$max_secs" =~ ^[1-9][0-9]*$ ]]; then
echo "❌ max_secs must be a positive integer, got: $max_secs" >&2
exit 2
Expand Down Expand Up @@ -471,7 +472,7 @@ perf-large-scale-smoke max_secs="60":

# Fast pre-PR performance guard against a cached same-machine main baseline.
perf-no-regressions threshold="7.5": _ensure-uv
uv run benchmark-utils compare-ref --ref main --threshold {{threshold}} --dev --output benches/worktree_vs_main_compare_results.txt
uv run benchmark-utils compare-ref --ref main --threshold {{ threshold }} --dev --output benches/worktree_vs_main_compare_results.txt

# Run the selected CI benchmark suite for one compiler/code pair.
profile toolchain="" code_ref="current":
Expand All @@ -481,8 +482,8 @@ profile toolchain="" code_ref="current":
command -v rustup >/dev/null || { echo "❌ 'rustup' not found. Install Rust via https://rustup.rs"; exit 1; }

repo_root="$(pwd)"
requested_toolchain="{{toolchain}}"
requested_ref="{{code_ref}}"
requested_toolchain="{{ toolchain }}"
requested_ref="{{ code_ref }}"
workdir="$repo_root"
cleanup_worktree=0

Expand Down Expand Up @@ -774,8 +775,8 @@ setup-tools:
fi

if ! have cargo-llvm-cov; then
echo " ⏳ Installing cargo-llvm-cov {{cargo_llvm_cov_version}} (cargo)..."
cargo install --locked cargo-llvm-cov --version {{cargo_llvm_cov_version}}
echo " ⏳ Installing cargo-llvm-cov {{ cargo_llvm_cov_version }} (cargo)..."
cargo install --locked cargo-llvm-cov --version {{ cargo_llvm_cov_version }}
else
echo " ✓ cargo-llvm-cov"
fi
Expand Down Expand Up @@ -886,11 +887,11 @@ spell-check: _ensure-typos

# Create an annotated git tag from the CHANGELOG.md section for the given version
tag version: python-sync
uv run tag-release {{version}}
uv run tag-release {{ version }}

# Replace an existing annotated tag from the CHANGELOG.md section.
tag-force version: python-sync
uv run tag-release {{version}} --force
uv run tag-release {{ version }} --force

# Testing
# test: runs default-profile benchmark/release compile checks plus all tests.
Expand Down Expand Up @@ -950,7 +951,7 @@ toml-check: _ensure-uv
files+=("$file")
done < <(git ls-files -z '*.toml')
if [ "${#files[@]}" -gt 0 ]; then
printf '%s\0' "${files[@]}" | xargs -0 -I {} uv run python -c "import tomllib; tomllib.load(open('{}', 'rb')); print('{} is valid TOML')"
printf '%s\0' "${files[@]}" | xargs -0 -I {} uv run python -c "import sys, tomllib; tomllib.load(open(sys.argv[1], 'rb')); print(f'{sys.argv[1]} is valid TOML')" {}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
else
echo "No TOML files found to check."
fi
Expand Down
2 changes: 0 additions & 2 deletions src/core/algorithms/incremental_insertion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ use crate::triangulation::delaunay::DelaunayTriangulationValidationError;
use std::fmt;
use std::hash::{Hash, Hasher};

pub use crate::core::operations::{InsertionOutcome, InsertionResult, InsertionStatistics};

/// Reason for hull extension failure.
///
/// # Examples
Expand Down
Loading
Loading