Implement 'exact' authalic latitude->geographic latitude and use it in +proj=aea/cea/laea/eqearth/healpix/rhealpix#4441
Conversation
…n +proj=aea/cea/laea/eqearth/healpix/rhealpix Fixes OSGeo#4440
|
@kbevers I'm not sure if this is appropriate for backport. This is somewhere in between a new feature and a bugfix. This could cause downstream software to potentially have failures in their test suite if they test coordinates with sufficient precision, so perhaps not appropriate for a bugfix release. |
|
@cffk was suggesting something in 2023 about the authalic latitude in https://lists.osgeo.org/pipermail/proj/2023-March/010956.html |
Let's call it a new feature, this is a changed approach that delivers better accuracy in some cases. @cffk since you've written the book (well, sort of) on this topic it would be foolish not request your input here :-) |
|
I was going to add the reference in |
I'll take a look and give feedback tomorrow (03-21). |
|
A. Addressing this PR is the narrowest way...
return phi;
// Given beta, solve
// f(phi) = qp*sin(beta)/(1-e^2) - q(phi)/(1-e^2)
// for phi, where
// q(phi)/(1-e^2) = sin(phi)/(1 - e^2*sin(phi)^2) + atanh(e*sin(phi))/e
// and
// df(phi)/dphi = - dq(phi)/dphi / (1-e^2)
// = - 2 * (1-e^2) * cos(phi) / (1 - e^2*sinphi^2)^2
B. However, widening the scope of this comment ... The method for computing the auxiliary latitude Hence, C. Finally ... A longer range goal would be to replace the ill-conditioned formula for Indeed And it might be extended to support the conversions in In summary, I recommend A. Now also would be a good time to implement |
|
@cffk Thanks for the review. I've added a commit using your comments A. B and C are a bit beyond my understanding / available time unfortunately. If we were going to do this, I believe the most straightforward way would probably to just borrow your implementation AuxLatitude.hpp, AuxLatitude.cpp from https://doi.org/10.5281/zenodo.7382666 . |
cffk
left a comment
There was a problem hiding this comment.
Let's go with this. To address Even's remark about absorbing my AuxLatitude implementation: I fear this may be overkill. Perhaps @jjimenezshaw can be persuaded to start a cleanup of latitude.cpp. Or maybe I'll take a crack at doing the two authalic conversions.
|
hum it looks like using atanh() in the forward path degrades the accuracy on i386 at the pole. Maybe we should revert that part ? |
How are you measuring this? The My recommendation: keep the |
well, https://github.com/OSGeo/PROJ/actions/runs/13995771272/job/39190443832?pr=4441 now fails, whereas it didn't before my additional commit I can comment out the problematic test points / relax their precision requirements for now |
This follows on the discussion in OSGeo#4441. In particular... latitudes.cpp now offers methods for converting between auxiliary laitudes using trigonometric series whose coefficients are power series in n. The series are evaluated using Clenshaw summation and Horner's method. For small flattening, these often offer better accuracy than the analytical expressions. Now mlfn.cpp and tmerc.cpp use these conversions, simplifying the implementations in these files. In particular tmerc's functions gatg and clens (which puzzlingly seemed to do exactly the same thing!) have been removed. tmerc's clenS (with a capital "S") stays -- it does complex Clenshaw summation Along the way, I've simplified pj_conformal_lat and pj_conform_lat_inverse in latitudes.cpp. For the former, I've substituted a better conditioned formula; for the latter, I used the existing (and more efficent) approach implemented in pj_sinhpsi2tanphi. The computation of authalic latitudes in latitudes.cpp now uses the series method if the flattening is small. However some of the test cases of the spillhaus projection use large flattening (is this really necessary?); so I've had to retain the poorly conditioned analytical formulas as well. If we really wanted to support large flattening in this case, it's necessary to evaluate the authalic latitude using Eqs. (52), (53), (54) of "On auxiliary latitudes" (https://arxiv.org/abs/2212.05818) and using Newton's method on the tangents of the angles for the inverse, using Eq. (57). I don't see the need for these at present. I've simplified the interface somewhat: passing P instead of P->e, P->onees, etc. separately; dropping "_coeffs" off the q function name and the tagging of the inverse function name with "_exact". I had hoped to retire the external use of Snyder's q(sinphi). However, some equal area projections, e.g., the cylindrical version, really do need this function instead of the authalic latitude directly.
This follows on the discussion in #4441. In particular latitudes.cpp now offers methods for converting between auxiliary laitudes using trigonometric series whose coefficients are power series in n. The series are evaluated using Clenshaw summation and Horner's method. For small flattening, these often offer better accuracy than the analytical expressions. Now mlfn.cpp and tmerc.cpp use these conversions, simplifying the implementations in these files. In particular tmerc's functions gatg and clens (which puzzlingly seemed to do exactly the same thing!) have been removed. tmerc's clenS (with a capital "S") stays -- it does complex Clenshaw summation Along the way, I've simplified pj_conformal_lat and pj_conform_lat_inverse in latitudes.cpp. For the former, I've substituted a better conditioned formula; for the latter, I used the existing (and more efficent) approach implemented in pj_sinhpsi2tanphi. The computation of authalic latitudes in latitudes.cpp now uses the series method if the flattening is small. However some of the test cases of the spillhaus projection use large flattening (is this really necessary?); so I've had to retain the poorly conditioned analytical formulas as well. If we really wanted to support large flattening in this case, it's necessary to evaluate the authalic latitude using Eqs. (52), (53), (54) of "On auxiliary latitudes" (https://arxiv.org/abs/2212.05818) and using Newton's method on the tangents of the angles for the inverse, using Eq. (57). I don't see the need for these at present. I've simplified the interface somewhat: passing P instead of P->e, P->onees, etc. separately; dropping "_coeffs" off the q function name and the tagging of the inverse function name with "_exact". I had hoped to retire the external use of Snyder's q(sinphi). However, some equal area projections, e.g., the cylindrical version, really do need this function instead of the authalic latitude directly.
Fixes #4440
$ echo 1020000 1562000 | bin/cs2cs epsg:3035 epsg:4937 -d 10 | bin/cs2cs epsg:4937 epsg:3035 -d 4
1020000.0000 1562000.0000 0.0000