docs: split Phase 9a into 9a.1 (CPEuclidean) + 9a.2 (InversiveDistance)
Audit during Phase 9a preparation revealed:
* The Java repo `varylab/conformallab` does NOT contain
`InversiveDistanceFunctional.java`. The original roadmap mention
was based on a misreading.
* The closest existing Java class is `CPEuclideanFunctional.java`
(260 lines, with FunctionalTest), implementing the Bobenko-Pinkall-
Springborn 2010 face-based circle-packing functional.
These two functionals are mathematically distinct (face-dual vs vertex-
based) but related: BPS-CP generalises inversive-distance via the
intersection angle parameter θ_e (I_ij = cos θ_e for orthogonal
limit, I_ij = 1 for tangential).
The roadmap is now split into:
- 9a.1 CPEuclideanFunctional (Java port + test, BPS 2010 reference)
- 9a.2 InversiveDistanceFunctional (from-literature, Luo 2004
+ Glickenstein 2011)
Both belong in Phase 9a; cross-validation between them in the
tangential limit (θ=0 ⇔ I=1) becomes a Phase 9a acceptance test.
The tutorial `doc/tutorials/add-inversive-distance.md` is corrected:
it no longer claims `InversiveDistanceFunctional.java` exists upstream,
and cites Luo 2004 + Glickenstein 2011 + Bowers-Stephenson 2004 instead.
Updated edge-length formula from incorrect hyperbolic cosh form to
the correct Luo §3 Euclidean form:
ℓ_ij² = exp(2u_i) + exp(2u_j) + 2 I_ij exp(u_i + u_j)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -75,11 +75,79 @@ mesh type.
|
|||||||
Java features from `de.varylab.discreteconformal` not yet in C++:
|
Java features from `de.varylab.discreteconformal` not yet in C++:
|
||||||
|
|
||||||
```
|
```
|
||||||
9a Inversive-distance functional (Luo 2004 / Bowers–Stephenson)
|
9a Circle-packing / inversive-distance functionals
|
||||||
|
───────────────────────────────────────────────
|
||||||
|
Status: discovered during 9a-prep audit (2026-05-19) that the
|
||||||
|
original roadmap mention "inversive_distance_functional.hpp" was
|
||||||
|
based on a misreading — the Java repo at de.varylab.discreteconformal
|
||||||
|
does NOT contain InversiveDistanceFunctional.java. It contains the
|
||||||
|
related CPEuclideanFunctional.java which is the face-dual variant
|
||||||
|
(Bobenko-Pinkall-Springborn 2010). These are two mathematically
|
||||||
|
distinct models that both belong in this phase. Plan split:
|
||||||
|
|
||||||
|
9a.1 CPEuclideanFunctional (FACE-based circle packing)
|
||||||
|
→ cp_euclidean_functional.hpp
|
||||||
|
Java reference: CPEuclideanFunctional.java (260 lines) + test
|
||||||
|
Mathematical reference:
|
||||||
|
Bobenko, Pinkall, Springborn (2010) — "Discrete conformal maps
|
||||||
|
and ideal hyperbolic polyhedra", Geom. Topol. 14, 379-426.
|
||||||
|
DOFs: ρ_f per FACE (log-radius of the face-circle)
|
||||||
|
Constants: θ_e per edge (intersection angle, π/2 = orthogonal)
|
||||||
|
φ_f per face (target face-angle sum, default 2π)
|
||||||
|
Energy: E(ρ) = -Σ_f φ_f·ρ_f
|
||||||
|
+ Σ_e [½·p(θ*_e, Δρ_e)·Δρ_e + Λ(θ*_e + p)]
|
||||||
|
where p = 2·atan(tan(θ*/2)·tanh(Δρ/2)),
|
||||||
|
Λ = Clausen function, θ* = π − θ.
|
||||||
|
Hessian: analytic, 2×2 per interior edge:
|
||||||
|
h_jk = sin(θ) / (cosh(Δρ) − cos(θ))
|
||||||
|
Gauge: first face is pinned (ρ_0 = 0)
|
||||||
|
|
||||||
|
New CGAL entry: CGAL::discrete_circle_packing_euclidean(mesh, np)
|
||||||
|
Test suite: test_cp_euclidean_functional.cpp
|
||||||
|
(Dodecahedron-with-removed-face, θ=π/2,
|
||||||
|
FD gradient check, FD-vs-analytic Hessian check)
|
||||||
|
|
||||||
|
9a.2 Inversive-distance functional (VERTEX-based)
|
||||||
→ inversive_distance_functional.hpp
|
→ inversive_distance_functional.hpp
|
||||||
Follows the exact same pattern as the three existing functionals.
|
Java reference: NONE (does not exist upstream)
|
||||||
→ newton_inversive_distance()
|
Mathematical reference:
|
||||||
→ New test suite: test_inversive_distance.cpp
|
Luo, F. (2004) "Combinatorial Yamabe Flow on Surfaces",
|
||||||
|
Commun. Contemp. Math. 6(5), 765-780.
|
||||||
|
Bowers, P. & Stephenson, K. (2004) "Uniformizing dessins
|
||||||
|
and Belyĭ maps via circle packing", Mem. AMS 170(805).
|
||||||
|
Glickenstein, D. (2011) "Discrete conformal variations and
|
||||||
|
scalar curvature on piecewise flat manifolds",
|
||||||
|
J. Diff. Geom. 87(2), 201-238 (analytic Hessian).
|
||||||
|
DOFs: u_i per VERTEX (u_i = log r_i)
|
||||||
|
Constants: I_ij per edge (inversive distance, computed
|
||||||
|
once from initial geometry:
|
||||||
|
I_ij = (ℓ_ij² − r_i² − r_j²)
|
||||||
|
/ (2 r_i r_j))
|
||||||
|
Θ_v per vertex (target cone angle, default 2π)
|
||||||
|
Edge length: ℓ_ij(u)² = e^{2u_i} + e^{2u_j} + 2 I_ij e^{u_i+u_j}
|
||||||
|
Angles: identical half-tangent atan2 form to Euclidean
|
||||||
|
Gradient: ∂E/∂u_v = Θ_v − Σ_{T∋v} α_v(T)
|
||||||
|
(Luo 2004 Lemma 3.1)
|
||||||
|
Energy: path integral E(u) = ∫₀¹⟨G(tu),u⟩dt
|
||||||
|
(Luo's 1-form is closed; no general closed form,
|
||||||
|
use 10-point Gauss-Legendre as in Euclidean)
|
||||||
|
Hessian: FD for MVP; analytic (Glickenstein 2011 eq. 4.6)
|
||||||
|
as future optimisation
|
||||||
|
Gauge: first vertex pinned (u_0 = 0)
|
||||||
|
|
||||||
|
New CGAL entry: CGAL::discrete_inversive_distance_map(mesh, np)
|
||||||
|
Test suite: test_inversive_distance_functional.cpp
|
||||||
|
(small triangle + quad + tetra, FD gradient
|
||||||
|
check, convergence test, special case I=1
|
||||||
|
coincides with tangential circle packing)
|
||||||
|
|
||||||
|
Cross-validation between 9a.1 and 9a.2 (Glickenstein 2011 §5):
|
||||||
|
In the tangential limit (θ_e = 0 in 9a.1 ⇔ I_ij = 1 in 9a.2),
|
||||||
|
both functionals describe the same circle packing. Their
|
||||||
|
converged radii must satisfy
|
||||||
|
ρ_f(9a.1) vs ½·log(r_i·r_j) (9a.2)
|
||||||
|
under the appropriate vertex↔face dual correspondence. This
|
||||||
|
cross-check is part of the Phase 9a acceptance tests.
|
||||||
|
|
||||||
9b Analytic HyperIdeal Hessian
|
9b Analytic HyperIdeal Hessian
|
||||||
→ Replace FD Hessian in hyper_ideal_hessian.hpp
|
→ Replace FD Hessian in hyper_ideal_hessian.hpp
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
# Tutorial: Porting the Inversive-Distance Functional (Phase 9a)
|
# Tutorial: Porting the Inversive-Distance Functional (Phase 9a.2)
|
||||||
|
|
||||||
This is a complete, step-by-step example of how to add a new functional
|
This is a complete, step-by-step example of how to add a new functional
|
||||||
to conformallab++. It ports `InversiveDistanceFunctional.java` from the
|
to conformallab++.
|
||||||
Java reference implementation (Luo 2004).
|
|
||||||
|
> **Note:** This tutorial implements the **vertex-based** inversive-distance
|
||||||
|
> circle packing of Luo (2004) and Glickenstein (2011). Despite an earlier
|
||||||
|
> draft of this document, the Java reference repository `varylab/conformallab`
|
||||||
|
> does **not** contain an `InversiveDistanceFunctional.java`. This is a
|
||||||
|
> from-the-literature implementation, validated by cross-checking against
|
||||||
|
> the **face-based** circle-packing functional `CPEuclideanFunctional.java`
|
||||||
|
> (Bobenko-Pinkall-Springborn 2010, see Phase 9a.1) in the tangential
|
||||||
|
> limit `I_ij = 1` ⇔ `θ_e = 0`.
|
||||||
|
|
||||||
**Prerequisite:** Read [doc/api/extending.md](../api/extending.md) first
|
**Prerequisite:** Read [doc/api/extending.md](../api/extending.md) first
|
||||||
for the general pattern. This tutorial fills in every detail for one
|
for the general pattern. This tutorial fills in every detail for one
|
||||||
@@ -12,22 +20,50 @@ specific case.
|
|||||||
|
|
||||||
## Mathematical background
|
## Mathematical background
|
||||||
|
|
||||||
Inversive distance (Luo 2004) uses a different edge-length update formula:
|
Inversive distance circle packing parametrises each vertex by a circle of
|
||||||
|
radius `r_i = exp(u_i)`. For each edge, the *inversive distance* `I_ij`
|
||||||
|
between the two adjacent circles is a fixed constant of the edge, computed
|
||||||
|
once from the initial geometry:
|
||||||
|
|
||||||
```
|
```
|
||||||
Given inversive distances I_{ij} ∈ ℝ for each edge {i,j}:
|
I_ij = (ℓ_ij² − r_i² − r_j²) / (2 r_i r_j) (Bowers-Stephenson)
|
||||||
|
|
||||||
cosh(l̃_{ij}) = I_{ij} · cosh((u_i + u_j) / 2)
|
|
||||||
+ (cosh²((u_i - u_j) / 2) - 1) · ...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
For the Euclidean version the angle formula is the same law of cosines,
|
| Range of `I_ij` | Geometric meaning |
|
||||||
but the log-lengths Λ̃ are computed differently from the u-vector.
|
|---|---|
|
||||||
|
| `I_ij = 1` | Tangential circles (Koebe-style) |
|
||||||
|
| `I_ij = cos φ ∈ (0,1)` | Overlapping circles with intersection angle φ |
|
||||||
|
| `I_ij = 0` | Orthogonal circles |
|
||||||
|
| `I_ij ∈ (−1, 0)` | Disjoint circles (inversive-distance > 1) |
|
||||||
|
|
||||||
**Reference:** Luo, F. (2004). *Combinatorial Yamabe Flow on Surfaces*.
|
The edge length is then determined by the radii via:
|
||||||
Communications in Contemporary Mathematics, 6(5), 765–780.
|
|
||||||
|
|
||||||
**Java source:** `de.varylab.discreteconformal.functional.InversiveDistanceFunctional`
|
```
|
||||||
|
ℓ_ij(u)² = exp(2 u_i) + exp(2 u_j) + 2 I_ij exp(u_i + u_j) (Luo 2004 §3)
|
||||||
|
```
|
||||||
|
|
||||||
|
The angle formula is the same law of cosines (numerically stable
|
||||||
|
half-tangent form) as the Euclidean functional — only the edge-length
|
||||||
|
mapping changes. The gradient
|
||||||
|
|
||||||
|
```
|
||||||
|
∂E/∂u_i = Θ_i − Σ_{T ∋ i} α_i(T)
|
||||||
|
```
|
||||||
|
|
||||||
|
is the standard Yamabe-flow gradient (Luo 2004 Lemma 3.1).
|
||||||
|
|
||||||
|
**Primary references:**
|
||||||
|
- Luo, F. (2004). *Combinatorial Yamabe Flow on Surfaces*.
|
||||||
|
Communications in Contemporary Mathematics, 6(5), 765–780.
|
||||||
|
- Bowers, P. L. & Stephenson, K. (2004). *Uniformizing dessins and
|
||||||
|
Belyĭ maps via circle packing*. Memoirs of the AMS 170(805).
|
||||||
|
- Glickenstein, D. (2011). *Discrete conformal variations and scalar
|
||||||
|
curvature on piecewise flat manifolds*. J. Differential Geometry
|
||||||
|
87(2), 201–238 (analytic Hessian, eq. 4.6).
|
||||||
|
|
||||||
|
**Java source:** none — this functional is implemented from the
|
||||||
|
above papers. See [doc/roadmap/phases.md](../roadmap/phases.md) §9a for
|
||||||
|
the historical clarification.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user