Ports the small but pervasive de.jreality.math.Pn surface that the Java
algorithmic core uses across every not-yet-ported geometric phase:
HyperbolicLayout, SphericalLayout, FundamentalPolygon (9c), KoebePolyhedron
(10c'), quasi-isothermic (10e), hyperelliptic theta, CircleDomain (11c).
Porting it once unblocks all downstream consumers instead of re-deriving
the metric ad hoc per phase.
pn_geometry.hpp — header-only, Eigen, ~120 LOC:
PnMetric { EUCLIDEAN=0, ELLIPTIC=+1, HYPERBOLIC=-1 } matching jReality.
pn_inner_product — bilinear form per signature.
pn_norm / pn_dehomogenize / pn_set_to_length / pn_normalize.
pn_distance_between — Euclidean (spatial), elliptic (acos), hyperbolic (acosh).
pn_linear_interpolation — affine (E) and slerp (S/H constant-speed geodesic).
HYPERBOLIC uses the timelike-positive ("upper-sheet") convention, identical to
the already-verified projective_math.hpp::hyperbolicDistance; pn_distance_between
is regression-anchored against it in the tests.
test_pn_geometry.cpp — 6 tests, all GREEN:
InnerProductSignatures, EuclideanDistance, EllipticDistanceIsAngle,
HyperbolicDistanceClosedFormAndAnchor (+ projective_math.hpp anchor),
NormAndScaling, LinearInterpolationGeodesic.
doc/roadmap/java-parity.md — new "Infrastructure / support layers" section:
de.jreality.math.Pn → pn_geometry.hpp (partial, 6 fns covering core usage)
de.jreality.math.Rn → Eigen (no separate port needed)
MatrixBuilder → not yet (only needed for hyperelliptic theta)
conformallab XML types → not planned (GUI persistence, not algorithmic)
246/246 cgal tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>