-
-
Notifications
You must be signed in to change notification settings - Fork 363
libgis: use GeographicLib from PROJ #1283
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
metzm
commented
Jan 29, 2021
- use GeographicLib for geodesic distance and area calculations (see [Feat] Use GeographicLib for computing ellipsoidal areas #1235)
CentOS 7 is out with this PR because it gets proj-4.8.0 from EPEL which is too old... The big question is, if we accept the fact that this PR does not work with stock CentOS 7, which the GRASS community needs to answer. |
@metzm Markus, you asked me to review but even I am a somewhat experienced GIS user I unfortunately understand very little about coding. |
Maybe @kbevers is willing to take a look at this PR? |
Looks about right to me but I am in no way an expert in the geodesic code so take my blessings with a grain of salt |
I have tested with testfile linked in QGIS ml: With this PR (proj=7.2.1) With G 7.8.5 (proj=7.1.1) QGIS 3.10.11 (proj=5.2.0) For The results seem to me to be correct, with no regression. |
I've tested and can confirm that in current trunk, results between GRASS GIS and the GeographicLib implementation in R (geosphere) are identical (to the sq m):
Results in GRASS GIS also seem stable when generalizing and more generalized versions do concur with the geosphere output:
And testing with the data described in this old trac ticket the results are fairly stable:
But results are not identical to geosphere results:
Any idea why ? |
Testing the example of mlennert, one reason for different results with R geosphere is that a and f where not given, however, using the same a and f as in GRASS I still don't get the same results, and my results with GRASS differ from the results of mlennert with GRASS:
poly
poly_gen_000000001
poly_gen_000000003
poly_gen_00000001
If mlennert also used PROJ 7.2.1, there must be some numerical instability in the GeographicLib as included in PROJ, otherwise differences between mlennert and metzm might be due to different PROJ versions. Altogether, the observed differences can not even be explained with single precision floating point limitations. GeographicLib can no longer be used as reference because GeographicLib itself produces different results on different systems. My results with the R geosphere package are identical to those of mlennert, but according to the geosphere documentation, a and f need to be specified. |
For my tests with R geosphere, the precision of a and f was too low. Using more precise values |
There is also the Planimeter tool of GeographicLib. Thus there are three different implementations of the algorithm of Charles Karney: Planimeter, geodesic.[c|h] in PROJ and R geosphere. Unfortunately with four different results:
Differences begin to occur already at the fourth significant decimal digit, latest at the sixth significant decimal digit. This is IMHO too high. |
Have you also used the "Planimeter" tool with the "-E" option? Anyway, I think geodesic/ellipsoidal area calculation are not actual useful for polygons of very small extension (like the "training_single" layer which is about 0.1 square meters). |
Same result. Does not answer the question why Planimeter and PROJ geodesic provide different results.
But PROJ geodesic.h states that "for the WGS84 ellipsoid, the errors are less than 15 nanometers". Thus I expect accurate and consistent (!) results for our example which is with > 0.1 spm huge relative to the given errors. I could create a new issue in PROJ for the inconsistency between GeographicLib and geodesic.[c|h] in PROJ. |
I think it's time to call in the cavalry. @cffk, above are showcased inconsistencies between various setups using geodesic calculations from GeographicLib - any insight as to why? |
OK, I'll take a look. The intention is that PROJ's geodesic calculations (C code) should mirror very accurately what you get from GeographicLib (C++ code). |
I would also expect consistent results. Anyway, the Planimeter online tool description at https://geographiclib.sourceforge.io/cgi-bin/Planimeter states that: "The result for the perimeter is accurate to about 15 nm per vertex. The result for the area is accurate to about 0.1 m2 per vertex." The same is stated in C. F. F. Karney, Algorithms for geodesics, J. Geodesy 87, 43-55 (2013): "The round-off errors in the direct and inverse methods are less than 15 nanometers and the error in the computation of the area S12 is about 0.1 m2." |
I'm on Debian testing. Is there any env variable I need to set or something ? Is there a way to test that I'm really using the GeographicLib ? |
0.1 m2 per vertex seems quite a lot actually, especially for small polygons. Is this completely independent of the size ? IIUC, the small test polygon used above has 45 vertices, so that would mean an expected error of 4.5m2 ? |
If you use this PR, geodesic.[c|h] (the C version of GeographicLib) from PROJ is automatically used. |
Judging from libgis revision: 8b4c498 it is not this PR |
The "exact" area of the 44-sided training_single polygon is
if the coordinates in the KML file are treated as exact decimal numbers.
so the error is 30 mm^2 or about 1 mm^2 per vertex. The error in the My estimate of the error of 0.1 m^2 per vertex tries to capture the
Almost certainly, the calculation of the area benefits from a As to the question of whether 100 mm^2 = (1 cm)^2 (let's say) is too big It would be difficult to wring much more accuracy out of a method using
where A is the area of the ellipsoid. |
For reference:
So, the value of the area of this particular polygon, calculated with the current GRASS/QGIS implementation of the geodesic area calculation algorithm, differs by about 1E-10 square meters from the "exact" value. [1] GRASS version: 7.8.5 - Code revision: 2b6ab28 - Windows 7 64 bit (OSGeo4W 64 bit) |
How about the polygon from the QGIS issue qgis/QGIS#40888? For that the difference in area between current QGIS and GeographicLib was 0.654%.
|
This tiny test polygon with a size of about 0.1263 sqm seems to hit the limits of floating point calculations and trigonometric functions. For larger areas, the Planimeter tool of GeographicLib and the corresponding C version in PROJ provide identical results. Let's assume that GeographicLib provides the most accurate results for geodesic distance and area calculations available in the osgeo world. The different results of the Planimeter tool of GeographicLib and the corresponding C version in PROJ might be explained by different compilers and/or compiler flags. In my case, using -fno-fast-math with PROJ changes the size of the tiny test polygon from 0.126272547475285 to 0.12634739123375 which is very close to 0.126347391348170, the "exact" value calculated by @cffk. Planimeter's 0.12638 from the package manager of my Linux distro is thus a bit off. Compilers and compiler flags seem to make a difference, explaining any inconsistencies for extreme cases between he Planimeter tool of GeographicLib and the corresponding C version in PROJ. AFAIK, QGIS uses the same (or very similar) algorithm to calculate area sizes as the GRASS native algorithm and is thus not suitable for comparison of accurate results, only for comparison of consistency. |
The "exact" area here is (assuming coordinates are lon,lat and WGS84):
|
One possible source of confusion is that the online planimeter tool is compiled to use |
If you mean that the difference is perhaps too small for having any practical meaning, it may be true with this tiny polygon but have a look at the half-a-Finland polygon that I pasted as a comment. That shows 0.654% difference in areas.
|
Using this PR (with PROJ 7.2.1) the same polygon gives the result 251199344354.431 which is pretty close to the "exact" area. |
Close enough for me. Now that I got my PROJ compiler flags right, I get in all reported cases results very close to these "exact" results of GeographicLib. For me, the inconsistencies are resolved. |
The relatively big difference between the "old" grass/qgis and the new calculation (this PR) for the Finland polygon, may perhaps display the limitations of the old method. Testing a polygon (~ Uganda) along the equator: gives ~0.012% difference:
|
Bumping up milestone as 8.0.1 is due in two days, while this has not been part of RC1 and there has not been activity for some time. |
FYI, I comment on GRASS's current method of calculating areas (which assumes straight edges in a plate carree projection) in https://geographiclib.sourceforge.io/C++/2.4/rhumb.html#platecarreearea Bottom line:
Is this PR likely to make it into GRASS 8.5.0? It seems that it's just a matter of "doing it". |
Solved conflicts of the existing code of the PR. |
* use GeographicLib for geodesic distance and area calculations (see OSGeo#1235)
This is causing test failure in v.import (across platforms):
@metzm any idea? v.proj uses G_distance to compute segment lengths for densification, so different results probably make sense, but I was surprised that they differ so much. |