Repository navigation
Fix sign convention in BFF::dirichletToNeumann - #264
joaoajmatos wants to merge 1 commit into
Conversation
dirichletToNeumann() returned the exterior angles for -u, while computeBoundaryPositions() and neumannToDirichlet() use lengths scaled by exp(+u). flattenFromScaleFactors() therefore produced inconsistent layouts for any non-constant u, e.g. when placing cone singularities and cutting to the boundary before flattening. flatten() (u = 0) was unaffected. Adds test/src/boundary_first_flattening_test.cpp: DtN/NtD round trip, scale-factor vs exterior-angle layouts, and a flat disk with one cone cut to the boundary. All three fail on v1.1.0 and pass with this change. Fixes nmwsharp#263
Sign convention error in
|
| Quantity | Analytic | v1.1.0 | Patched |
|---|---|---|---|
| Cut side a | 1.08646 | 1.08050 | 1.08612 |
| Cut side b | 1.08646 | 1.08050 | 1.08612 |
| Angle at the cut | notch 0.5 | overlap 0.5 | notch 0.5 |
| Inverted triangles at the cone | 0 | 16 | 0 |
The residual 0.03% between the patched side length and the analytic sector comes from the mesh (20 rings × 64 sectors) approximating the continuum cone; it shrinks with refinement.
5. Fix
Vector<double> BFF::dirichletToNeumann(const Vector<double>& uBdy) {
// Interior: Lii u_i = -(Omegai + Lib u_b) (zero target curvature, lengths scale by e^{+u}
// as in computeBoundaryPositions and neumannToDirichlet). Boundary: k = Omegab + Lbi u_i + Lbb u_b.
return Omegab - (Lib.transpose() * Liisolver->solve(Omegai + Lib * uBdy)) + Lbb * uBdy;
}Two signs change. No API change, and no change to flatten() results.
6. Regression tests
New file test/src/boundary_first_flattening_test.cpp, registered in test/CMakeLists.txt. The mesh is a flat unit disk built as a polar grid: a centre vertex, 20 rings of 64 vertices. A "slit" variant duplicates the ring vertices on the ray
| Test | What it checks | v1.1.0 | Patched |
|---|---|---|---|
DirichletNeumannRoundTrip |
|
FAIL (0.7275) | PASS |
ScaleFactorsMatchExteriorAngles |
flattenFromScaleFactors(u) equals flattenFromExteriorAngles(k(u)) up to rigid motion and the uniform scale |
FAIL (0.1803) | PASS |
ConeFromScaleFactorsIsIsometricOnTheCut |
notch angle equals the cone angle; cut sides equal; outline length within 0.00628 of 3D | FAIL (notch off by 2.3555) | PASS |
Full suite:
| Tree | Tests | Result |
|---|---|---|
| v1.1.0 + new tests (source unpatched) | 201 | 198 pass, 3 fail (the new ones) |
| v1.1.0 + patch + new tests | 201 | 201 pass |
7. Reproducibility
# pristine v1.1.0 with the submodule (tarballs omit it)
git clone --branch v1.1.0 https://github.com/nmwsharp/geometry-central.git
cd geometry-central && git submodule update --init
# A: tests only B: full patch
git apply --include='test/*' bff-dtn-sign.patch # or: git apply bff-dtn-sign.patch
cmake -S test -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
ninja -C build geometry-central-test
./build/bin/geometry-central-test --gtest_filter='BFFSuite.*'
./build/bin/geometry-central-testToolchain used: Apple clang (Xcode 27.2), Eigen 3.4.0, Ninja. The BFF results were identical on two independent builds (v1.1.0 and current master).
8. Workaround for v1.1.0 users
Either call dirichletToNeumann(-u), or compute flattenFromBoth(u, k) directly. The second form does not depend on the library version.
References
R. Sawhney and K. Crane, "Boundary First Flattening", ACM Transactions on Graphics 37(1), 2017. N. Sharp et al., geometry-central, https://geometry-central.net.
Fixes #263.
dirichletToNeumann()returned the exterior angles for-uwhilecomputeBoundaryPositions()lays out withexp(+u), so any non-constant scalefactors (cones) came out with the wrong sign: a 0.5 rad notch became a 0.5 rad
overlap with inverted triangles at the cone, and the cut sides came out short.
flatten()andflattenFromExteriorAngles()were not affected. Algebra and a before/afterfigure are in the issue.
Change: two signs in
dirichletToNeumann(), plus a comment stating theconvention. No API change.
Tests: new
test/src/boundary_first_flattening_test.cpp(registered intest/CMakeLists.txt), three cases: a DtN/NtD round trip, scale-factor vsexterior-angle layouts on the same
u, and a flat unit disk with one interiorcone of angle 0.5 cut to the boundary (notch angle, cut-side lengths, outline).
All three fail on v1.1.0 and pass with this change; the full suite goes from
198 to 201 passing.