feat: output_uv_map for InversiveDistance, error for CP-Euclidean, reviewer trio
Three reviewer-meeting deliverables in one commit.
(1) output_uv_map for the two remaining DCE entries
─────────────────────────────────────────────────
* Discrete_inversive_distance.h: full implementation. After Newton,
reconstruct effective Euclidean edge lengths from the converged
log-radii via the Bowers-Stephenson identity
`ℓᵢⱼ² = rᵢ² + rⱼ² + 2·Iᵢⱼ·rᵢ·rⱼ`, populate a temporary
EuclideanMaps with `lambda0 = log(ℓᵢⱼ²)`, and reuse the existing
`euclidean_layout(mesh, 0, eucl)` priority-BFS. Per-vertex
Point_2 coordinates written into the user-supplied pmap.
Optional `normalise_layout(true)` applies the canonical PCA
centroid + major-axis rotation, same as the other 3 entries.
* Discrete_circle_packing.h: throws std::runtime_error with a
clear pointer to Phase 9c rather than silently producing
nonsense. CP-Euclidean is face-based; the faithful output is a
per-face circle packing in ℝ², not a per-vertex Point_2 map.
A true layout requires BPS-2010 §6 (~150 lines, on the porting
roadmap as Phase 9c). Failing loudly is the honest default.
Tests: 2 new cases in test_cgal_phase8b_lite.cpp
(OutputUvMap_InversiveDistance_PopulatesPmap;
OutputUvMap_CPEuclidean_ThrowsClearly). Both green.
Suite total now 259 (was 257, +2). CGAL subtotal: 234 → 236.
(2) Reviewer meeting documents
──────────────────────────
New directory doc/reviewer/ with three files:
* briefing.md — one-page orientation for the reviewer.
What the project is, where to look first
(https://tmoussa.codeberg.page/ConformalLabpp/), the headline
evidence (tests/coverage/sanitizers/license), what we want from
them, what's deferred and why, and the 5 questions in a separate
file.
* questions.md — the 5 concrete decisions we want their second
opinion on:
Q1 Phase 9c (port-literal vs re-derive)
Q2 Phase 9b-analytic (worth ~2 weeks for ~6× speedup?)
Q3 CP-Euclidean output_uv_map (build now or defer?)
Q4 CGAL submission strategy (one package or five?)
Q5 geometry-central cross-validation co-authorship
Plus an explicit "what would you say no to?" question at the
bottom — negative feedback is the highest-value information.
* agenda.md — my own internal playbook (NOT to be sent).
60-min flow: 5-min thank-you, 10-min architecture tour,
30-min for Q1-Q5 in the order Q4-Q1-Q2-Q5-Q3, 5-min "no"
question, 5-min wrap-up. Includes post-meeting memo template
to fill out in the 30 min after.
* README.md — index for the directory; says which file goes
to whom and when to send.
(3) locked-vs-flexible.md known-limitations update
─────────────────────────────────────────────
"output_uv_map covers 3 of 5 entries" → "covers 4 of 5".
CP-Euclidean's throws-clearly behaviour documented as a Phase 9c
deliverable rather than a passive gap.
Bonus: extended .codespellrc ignore list (acknowledgement, the
British-English spelling I used in agenda.md).
Verifications on this commit:
259/259 tests pass (0 skipped)
scripts/check-test-counts.sh: OK (23 + 236 = 259)
scripts/quality/license-headers.sh: OK (66/66 SPDX)
python3 scripts/quality/cgal-conventions.py: OK (0/6 violations)
scripts/quality/codespell.sh: OK (0 typos)
scripts/quality/shellcheck.sh: OK (0 findings)
python3 scripts/check-markdown-links.py: OK (143/143)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
committed by
Tarik Moussa
parent
32253a8f5e
commit
f25174ed69
@@ -288,6 +288,60 @@ TEST(CGALPhase8bLite, OutputUvMap_HyperIdeal_PointsInPoincareDisk)
|
||||
// No assertion needed; this is documented behaviour.)
|
||||
}
|
||||
|
||||
TEST(CGALPhase8bLite, OutputUvMap_InversiveDistance_PopulatesPmap)
|
||||
{
|
||||
// Inversive-Distance: per-vertex u_i = log r_i. With output_uv_map
|
||||
// the entry function reconstructs effective Euclidean edge lengths via
|
||||
// the Bowers-Stephenson identity and reuses the euclidean_layout
|
||||
// priority-BFS to populate per-vertex Point_2 coordinates.
|
||||
using K = CGAL::Simple_cartesian<double>;
|
||||
auto mesh = make_quad_strip();
|
||||
|
||||
auto uv_map = mesh.add_property_map<Vertex_index, K::Point_2>(
|
||||
"v:test_uv_id", K::Point_2(0, 0)).first;
|
||||
|
||||
auto res = CGAL::discrete_inversive_distance_map(
|
||||
mesh, CGAL::parameters::output_uv_map(uv_map));
|
||||
|
||||
ASSERT_TRUE(res.converged) << "ID Newton did not converge on quad_strip";
|
||||
EXPECT_EQ(res.u_per_vertex.size(), num_vertices(mesh));
|
||||
// Every UV must be finite; not all zero.
|
||||
bool any_nonzero = false;
|
||||
for (auto v : mesh.vertices()) {
|
||||
const auto& p = uv_map[v];
|
||||
ASSERT_TRUE(std::isfinite(p.x()));
|
||||
ASSERT_TRUE(std::isfinite(p.y()));
|
||||
if (std::abs(p.x()) > 1e-9 || std::abs(p.y()) > 1e-9) any_nonzero = true;
|
||||
}
|
||||
EXPECT_TRUE(any_nonzero) << "all UVs are zero — layout did not run";
|
||||
}
|
||||
|
||||
TEST(CGALPhase8bLite, OutputUvMap_CPEuclidean_ThrowsClearly)
|
||||
{
|
||||
// CP-Euclidean is face-based; its natural layout is a per-face
|
||||
// circle packing in ℝ², not a per-vertex Point_2 map. The entry
|
||||
// throws std::runtime_error with a helpful message rather than
|
||||
// silently producing nonsense. See doc/architecture/locked-vs-flexible.md.
|
||||
using K = CGAL::Simple_cartesian<double>;
|
||||
auto mesh = make_quad_strip();
|
||||
|
||||
auto uv_map = mesh.add_property_map<Vertex_index, K::Point_2>(
|
||||
"v:test_uv_cp", K::Point_2(0, 0)).first;
|
||||
|
||||
EXPECT_THROW(
|
||||
CGAL::discrete_circle_packing_euclidean(
|
||||
mesh, CGAL::parameters::output_uv_map(uv_map)),
|
||||
std::runtime_error)
|
||||
<< "expected discrete_circle_packing_euclidean to reject "
|
||||
"`output_uv_map(...)` (face-based DOF, Phase 9c).";
|
||||
|
||||
// Sanity: without output_uv_map the entry function still works fine.
|
||||
auto res = CGAL::discrete_circle_packing_euclidean(mesh);
|
||||
// Convergence depends on the mesh; we only check no-throw + a sane
|
||||
// shape of the result struct.
|
||||
EXPECT_EQ(res.rho_per_face.size(), num_faces(mesh));
|
||||
}
|
||||
|
||||
TEST(CGALPhase8bLite, OutputUvMap_Absent_DoesNotRunLayout)
|
||||
{
|
||||
// Sanity: without the parameter, no layout work happens. Verified
|
||||
|
||||
Reference in New Issue
Block a user